﻿using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IceMan.Domain
{
    public class MainState : BindableBase
    {
        private Config config;
        private IStateStore stateStore;

        public MainState()
        {
            MaterialCountMap[Strawberry.Default.Name] = 0;
            MaterialCountMap[Chocolates.Default.Name] = 0;
            MaterialCountMap[IceCream.Default.Name] = 0;
        }

        public void InitRef(Config config, IStateStore stateStore)
        {
            this.config = config;
            this.stateStore = stateStore;

            // 初始化三个材料的数量
            InitMatCount(Strawberry.Default);
            InitMatCount(Chocolates.Default);
            InitMatCount(IceCream.Default);
        }

        private void InitMatCount(IMaterialType materialType)
        {
            materialType.ResetCount(MaterialCountMap[materialType.Name]);
        }

        #region 需要持久化的属性
        /// <summary>
        /// 材料剩余数量，包含多种材料。key为材料名称
        /// </summary>
        private int materialCount;
        public int MaterialCount
        {
            get { return materialCount; }
            set { SetProperty(ref materialCount, value); }
        }

        /// <summary>
        /// 保存材料数量的信息，key为材料名称，value为材料数量
        /// </summary>
        public Dictionary<string, int> MaterialCountMap { get; set; } = new Dictionary<string, int>();

        /// <summary>
        /// 材料不足时，发出警告
        /// </summary>
        private string alertContent;
        public string AlertContent
        {
            get { return alertContent; }
            set { SetProperty(ref alertContent, value); }
        }

        /// <summary>
        /// 日志队列，记录两个窗口分别执行到了哪一步，
        /// 程序启动时，检测此属性，用户恢复上次未执行完成的操作
        /// </summary>
        public LogEntry[] LogQueue { get; set; } = new LogEntry[3];
        #endregion


        public void AddWindow_1Log(IMaterialType materialType, bool isLastMaterial)
        {
            AddLogInternal(0, WorkType.Window1, materialType, isLastMaterial);
        }

        public void AddWindow_2Log(IMaterialType materialType, bool isLastMaterial)
        {
            AddLogInternal(1, WorkType.Window2, materialType, isLastMaterial);
        }

        public void AddReplaceMaterialLog(IMaterialType materialType, bool isLastMaterial)
        {
            AddLogInternal(2, WorkType.ReplaceMaterial, materialType, isLastMaterial);
        }

        private void CheckMaterialCount()
        {
            if (MaterialCount < config.MaterialAlertCount)
            {
                AlertContent = "材料即将不足，请尽快更换材料";
            }
            else
            {
                AlertContent = string.Empty;
            }
        }

        private void AddLogInternal(int queueIndex, WorkType type, IMaterialType materialType, bool isLastMaterial)
        {
            if (isLastMaterial)
            {
                LogQueue[queueIndex].OpType = WorkType.None;
            }
            else
            {
                LogQueue[queueIndex].OpType = type;
                LogQueue[queueIndex].FinishedState = materialType.Name;

                if (type == WorkType.ReplaceMaterial)
                {
                    // 重置数量
                    materialType.ResetCount(config.MaterialAddCount);
                }
                else
                {
                    // 减少数量
                    materialType.ReduceCount();
                }

                // 更新材料数量Map
                MaterialCountMap[materialType.Name] = materialType.RemainCount;

                // 更新剩余可制作数量
                MaterialCount = MaterialCountMap.Values.Min();

                // 更新告警信息
                CheckMaterialCount();
            }

            // 此方法内部使用了锁
            stateStore.Save(this);
        }

        /// <summary>
        ///  检测上次退出时，是否所有日志都是 正确状态
        ///  
        /// 如果
        /// </summary>
        /// <returns></returns>
        public void InitStateByLog(StateContainer window1State, StateContainer window2State, StateContainer replaceMaterialState)
        {
            if (LogQueue[0].OpType != WorkType.None)
            {
                // 窗口1 上次关闭时，有未完成的任务
                window1State.ChangeStateTo(LogQueue[0].FinishedState);
            }


            if (LogQueue[1].OpType != WorkType.None)
            {
                // 窗口2 上次关闭时，有未完成的任务
                window2State.ChangeStateTo(LogQueue[1].FinishedState);
            }


            if (LogQueue[2].OpType != WorkType.None)
            {
                //  上次关闭时，有未完成的更换材料任务
                replaceMaterialState.ChangeStateTo(LogQueue[2].FinishedState);
            }

            CheckMaterialCount();
        }
    }

    public enum StatyeType
    {
        /// <summary>
        /// 空闲中
        /// </summary>
        Idle = 0,
        /// <summary>
        /// 窗口1制作中
        /// </summary>
        OnlyMakeFirst = 1,
        /// <summary>
        /// 窗口2制作中
        /// </summary>
        OnlyMakeSecond = 2,

        /// <summary>
        /// 窗口1和窗口2同时在执行
        /// </summary>
        MakeFirstAnd_MakeSecond = OnlyMakeFirst | OnlyMakeSecond,

        /// <summary>
        /// 更换材料中
        /// </summary>
        ReplaceMaterial = 4,
    }

    public struct LogEntry
    {
        /// <summary>
        /// 操作类型
        /// </summary>
        public WorkType OpType { get; set; }
        /// <summary>
        /// 已完成的状态
        /// </summary>
        public string FinishedState { get; set; }
    }

    public enum WorkType
    {
        None,
        /// <summary>
        /// 窗口1操作
        /// </summary>
        Window1,
        /// <summary>
        /// 窗口2操作
        /// </summary>
        Window2,
        /// <summary>
        /// 更换材料操作
        /// </summary>
        ReplaceMaterial
    }
}
